package com.comcast.util;

import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.context.access.ContextSingletonBeanFactoryLocator;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternUtils;

import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Map;
import weblogic.utils.classloaders.GenericClassLoader;

public class AppContextSingletonBeanFactoryLocator extends
		ContextSingletonBeanFactoryLocator {
	private static final String DEFAULT_RESOURCE_LOCATION = "classpath*:beanRefContext.xml";
	private static final Map<ClassLoader, Map<String, BeanFactoryLocator>> appMap = new HashMap<ClassLoader, Map<String, BeanFactoryLocator>>();
	
	private static String rootResourceLocation = null;
	
	public static void setResourceLocation(String rLocation) {
		int index = rLocation.indexOf('-');  //ApplicationId sometime has '-' in it, Such as "HttpConnectorService-12"
		if (index != -1 ) {
			rLocation = rLocation.substring(0, index) + ".xml";
		}
		AppContextSingletonBeanFactoryLocator.rootResourceLocation = rLocation;
	}

	public static BeanFactoryLocator getAppInstance(Object appInstance) {
		String resourceLocation = AppContextSingletonBeanFactoryLocator.DEFAULT_RESOURCE_LOCATION; 
		if (AppContextSingletonBeanFactoryLocator.rootResourceLocation != null) {
			ClassPathResource cpr = new ClassPathResource(AppContextSingletonBeanFactoryLocator.rootResourceLocation);
			if (cpr.exists()) {
				resourceLocation = AppContextSingletonBeanFactoryLocator.rootResourceLocation;				
			} else {
				if (logger.isDebugEnabled()) {
					logger.debug(AppContextSingletonBeanFactoryLocator.rootResourceLocation + " is not presented, default one + " + DEFAULT_RESOURCE_LOCATION + " is used" );
				}
			}
		}

		if (!ResourcePatternUtils.isUrl(resourceLocation)) {
			resourceLocation = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resourceLocation; 
		}
		
		Map<String, BeanFactoryLocator> instances;

		synchronized (appMap) {
			instances = (Map<String, BeanFactoryLocator>)appMap.get(appInstance.getClass().getClassLoader());
			if (instances == null) {
				appMap.put(appInstance.getClass().getClassLoader(),
						instances = new HashMap<String, BeanFactoryLocator>());
			}
		}

		synchronized (instances) {
			if (logger.isDebugEnabled()) {
				logger.debug("ContextSingletonBeanFactoryLocator.getInstance(): instances.hashCode=" +
						 	 instances.hashCode() + ", instances=" + instances);
			}
			BeanFactoryLocator bfl = (BeanFactoryLocator) instances.get(resourceLocation);
			if (bfl == null) {
				bfl = new AppContextSingletonBeanFactoryLocator(resourceLocation);
				instances.put(resourceLocation, bfl);
			}
			return bfl;
		}

	}
	
	protected AppContextSingletonBeanFactoryLocator(String resourceLocation) {
		super(resourceLocation);
	}
}
